/**
 * @details: 
 * @brief: 
 * @version: 1.0
 * @author: liuri
 * @Date: 2021-10-05 05:15:32
 * @LastEditors: liuri
 * @LastEditTime: 2021-10-05 06:30:38
 * @FilePath: /TestProject/cPath/vtysh/cmd_terminal_type.c
 * @Copyright (C) 2021 liuri. All rights reserved.
 */

#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
#include <assert.h>
#include "cmd_terminal_type.h"


int cmd_range_match (const char *range, const char *str)
{
    #define DECIMAL_STRLEN_MAX 10
    char *p;
    char buf[DECIMAL_STRLEN_MAX + 1];
    char *endptr = NULL;
    unsigned long min, max, val;

    if (str == NULL)
        return 1;
    // val
    val = strtoul (str, &endptr, 10);
    if (*endptr != '\0')
        return 0;

    // min
    range++;
    p = strchr (range, '-');
    if (p == NULL)
    return 0;
    if (p - range > DECIMAL_STRLEN_MAX)
    return 0;
    strncpy (buf, range, p - range);
    buf[p - range] = '\0';
    min = strtoul (buf, &endptr, 10);
    if (*endptr != '\0')
        return 0;

    // max
    range = p + 1;
    p = strchr (range, '>');
    if (p == NULL)
        return 0;
    if (p - range > DECIMAL_STRLEN_MAX)
        return 0;
    strncpy (buf, range, p - range);
    buf[p - range] = '\0';
    max = strtoul (buf, &endptr, 10);
    if (*endptr != '\0')
        return 0;

    if (val < min || val > max)
        return 0;

    return 1;
}

int cmd_ipv4_match (const char *str)
{
    int ret;
    char buf[16];
    ret = inet_pton(AF_INET, str, buf);
    if( ret <= 0) return -1;
    return 0;
}

int cmd_ipv4_prefix_match (const char *str)
{
    int ret;
    char *p;
    char *dup_str;
    dup_str=strdup(str);
    p = strtok(dup_str, "//");
    char buf[16];
    ret = inet_pton(AF_INET, p, buf);
    if( ret <= 0)
    {
        free(dup_str);
        return -1;
    } 
    p = strtok(NULL, "//");
    if (NULL == p)
    {
        free(dup_str);
        return -1;
    }
    return 0;
}



int cmd_ipv6_match (const char *str)
{
    int ret;
    char buf[16];
    ret = inet_pton(AF_INET6, str, buf);
    if( ret <= 0) return -1;
    return 0;
}

int cmd_ipv6_prefix_match (const char *str)
{
    int ret;
    char *p;
    char *dup_str;
    dup_str=strdup(str);
    p = strtok(dup_str, "//");
    char buf[16];
    ret = inet_pton(AF_INET6, p, buf);
    if( ret <= 0)
    {
        free(dup_str);
        return -1;
    } 
    p = strtok(NULL, "//");
    if (NULL == p)
    {
        free(dup_str);
        return -1;
    }
    return 0;
}



/**
 * @brief: 根据 terminal 类型进行匹配
 * 
 * @param str 命令中的关键字
 * @param word 输入关键字的字段
 */
int cmd_word_match(int terminal, char *str, const char *word)
{    
    switch (terminal)
    {
        // 参数
        case TERMINAL_VARARG:
            return vararg_match;

        // 范围
        case TERMINAL_RANGE:
            if (cmd_range_match(str, word))
                return range_match;
        break;

        case TERMINAL_IPV6:
            if(!cmd_ipv6_match(word))
            {
                 return ipv6_match;
            }          
            break;
        case TERMINAL_IPV6_PREFIX:
            if(!cmd_ipv6_prefix_match(word))
            {
                 return ipv6_prefix_match;
            }  
            break;

        case TERMINAL_IPV4:
            if(!cmd_ipv4_match(word))
            {
                 return ipv4_match;
            } 
            break;

        case TERMINAL_IPV4_PREFIX:
            if(!cmd_ipv4_prefix_match(word))
            {
                 return ipv4_prefix_match;
            } 
            break;

        case TERMINAL_OPTION:
        case TERMINAL_VARIABLE:
            return extend_match;

        case TERMINAL_LITERAL:
            if (!strncmp(str, word, strlen(word)))
            {
                return partly_match;
            }
            break;

        default:
            assert (0);
    }

    return no_match;
}


#if 0
int main()
{
    int ret;
    ret = cmd_ipv4_match("12.2.2.2/2");
    printf("ret : %d \n", ret);
    ret = cmd_ipv4_match("12.2.2.2");
    printf("ret : %d \n", ret);
    ret = cmd_ipv4_match("12.2.2");
    printf("ret : %d \n", ret);

    ret = cmd_ipv4_prefix_match("12.2.2.2/2");
    printf("ret : %d \n", ret);
    ret = cmd_ipv4_prefix_match("123.2.2.2");
    printf("ret : %d \n", ret);
}

#endif
